// 这个文件要根据千寻SDK的接口函数进行修改，2023-08-26
// 最初版本实现基本功能即可，不需要封装千寻SDK所以的API函数

// 本文件是对中国移动CORS SDK库的封装，用于在lua内调用移动SDK库提供的10个接口函数
// 移动SDK的10个接口函数的声明在 inc/cmccsdk.h
// Alex at 2023-06-23

//    LuatOS的头文件, 位于LuatOS库的luat/include
//#include <stdio.h>
//#include <string.h>
#include "luat_base.h"   // 基础函数
#include "luat_malloc.h" // 内存分配函数
#include "luat_rtos.h"

#define LUAT_LOG_TAG "custom"

#include "luat_log.h"    // 日志函数,配套LUAT_LOG_TAG

#include "qxwz_types.h"
#include "qxwz_sdk.h"
#include "qxwz_user_impl.h"

#define DEMO_GGA_STR        "$GPGGA,000001,3112.518576,N,12127.901251,E,1,8,1,0,M,-32,M,3,0*4B"

#define DEMO_LOG(fmt, ...)  printf("[DEMO]"fmt, ##__VA_ARGS__)

static qxwz_uint32_t sdk_auth_flag = 0;
static qxwz_uint32_t sdk_start_flag = 0;
static qxwz_sdk_cap_info_t sdk_cap_info = {0};

static qxwz_void_t demo_show_caps(qxwz_sdk_cap_info_t *cap_info)
{
    qxwz_uint32_t loop = 0;

    DEMO_LOG("total capabilities: %d\n", cap_info->caps_num);
    for (loop = 0; loop < cap_info->caps_num; ++loop) {
        DEMO_LOG("idx: %d, cap_id: %u, state: %d, act_method: %d, expire_time: %llu\n",
            loop + 1,
            cap_info->caps[loop].cap_id,
            cap_info->caps[loop].state,
            cap_info->caps[loop].act_method,
            cap_info->caps[loop].expire_time);
    }
}

static qxwz_void_t demo_on_auth(qxwz_int32_t status_code, qxwz_sdk_cap_info_t *cap_info) {
    if (status_code == QXWZ_SDK_STAT_AUTH_SUCC) {
        sdk_auth_flag = 1;
        sdk_cap_info = *cap_info;
        demo_show_caps(cap_info);
    } else {
        DEMO_LOG("auth failed, code=%d\n", status_code);
    }
}

static qxwz_void_t demo_on_start(qxwz_int32_t status_code, qxwz_uint32_t cap_id) {
    DEMO_LOG("on start cap:status_code=%d, cap_id=%d\n", status_code, cap_id);
    sdk_start_flag = 1;
}


static qxwz_void_t demo_on_status(int code)
{
    DEMO_LOG(" on status code: %d\n", code);
}

static qxwz_void_t demo_on_data(qxwz_uint32_t type, const qxwz_void_t *data, qxwz_uint32_t len)
{
    DEMO_LOG(" on data: %d, ptr: %p, len: %d\n", type, data, len);

    switch (type) {
        case QXWZ_SDK_DATA_TYPE_RAW_NOSR:
            DEMO_LOG("QXWZ_SDK_DATA_TYPE_RAW_NOSR\n");
            break;
        default:
            DEMO_LOG("unknown type: %d\n", type);
    }
}

static void sdk_test()
{
    int ret = 0;
    /*
     * ** WARNING **
     * PLEASE FIRST CONFIRM THAT YOUR ACCOUNT IS AK OR DSK ?!?
     *
     * If your account is AK (usually with prefix `A`, like: `A00012dwejd`), set the `key_type` to `QXWZ_SDK_KEY_TYPE_AK`.
     * Otherwise, if it is DSK (usually with prefix `D`, like: `D0234jdwejd`), set the `key_type` to `QXWZ_SDK_KEY_TYPE_DSK`.
     * ** WARNING **
     */
    qxwz_sdk_config_t sdk_config = {0};

    /* AK or DSK ? Only choose one in the following codes! */
    /** AK */
    //sdk_config.key_type = QXWZ_SDK_KEY_TYPE_AK,
    //strcpy(sdk_config.key, "Your AK");
    //strcpy(sdk_config.secret, "Your AS");
    /** DSK */
    sdk_config.key_type = QXWZ_SDK_KEY_TYPE_DSK,
    strcpy(sdk_config.key, "D4ak3nkr8msa");
    strcpy(sdk_config.secret, "c255d15e837773bd");

    /* set device info */
    strcpy(sdk_config.dev_id, "icertk027");
    strcpy(sdk_config.dev_type, "RTK");

    /* set callbacks */
    sdk_config.status_cb    = demo_on_status;
    sdk_config.data_cb      = demo_on_data;
    sdk_config.auth_cb      = demo_on_auth;
    sdk_config.start_cb     = demo_on_start;


    /* If you need special format nosr data(QX format), use the segment*/
    qxwz_sdk_nosr_data_format_t data_fmt = QXWZ_SDK_NOSR_QX_FORMAT;
    ret = qxwz_sdk_config(QXWZ_SDK_CONF_NOSR_DATA_FORMAT, &data_fmt);
    DEMO_LOG("set nosr data format!ret=%d\n", ret);

    /* If you need set log level and output to file, use the segement.
     * If not use the segement, default only log target to console and log level is debug.
     */
    qxwz_sdk_log_conf_t log_info_conf = { 0 };
    log_info_conf.level = LOG_LEVEL_VERBOSE;          // log level
    log_info_conf.target = LOG_TARGET_ALL;            // log target
    strcpy(log_info_conf.dump_path, "Your dump path");// dump path must exist, otherwise close dump to file
    log_info_conf.is_color_console = 1;               // color console, 1: open, 0: close
    log_info_conf.is_close_crash_file = 0;            // crash file, 1: close , 0(default): open
    log_info_conf.log_file_size = 1* 1024 *1024;      // file size, range(1K~50M)
    log_info_conf.log_file_num = 5;                   // file num,  range(1~10)
    ret = qxwz_sdk_config(QXWZ_SDK_CONF_LOG_INFO, &log_info_conf);
    DEMO_LOG("set log info config!ret=%d\n", ret);

    unsigned int tick = 0;
    #ifdef CONFIG_DAEMON
    struct timeval tval = {0};
    gettimeofday(&tval, NULL);
    #endif
    /*
     * init sdk
     */
    ret = qxwz_sdk_init(&sdk_config);
    if (ret < 0) {
        printf("sdk init failed\n");
        goto END;
    }

    /*
     * do authentication
     */
    ret = qxwz_sdk_auth();
    if (ret < 0) {
        printf("call sdk auth failed\n");
        goto END;
    }

    while (1) {
        //#ifndef CONFIG_DAEMON /* if the sdk header file doesn't have qxwz_sdk_tick, don't invoke it */
        ret = qxwz_sdk_tick(tick++);
        if (ret < 0) {
            printf("sdk tick failed\n");
            break;
        }
        /* must need delay 100ms */
        /* Please use the delay function under the embedded platform.Such as `delay()` */
        luat_rtos_task_sleep(100);
        //#else
        luat_rtos_task_sleep(100);
        //#endif
        if ((++tick % 10) == 0) {
            /* upload GGA */
            qxwz_sdk_upload_gga(DEMO_GGA_STR, strlen(DEMO_GGA_STR));
        }

        if (sdk_auth_flag > 0) {
            sdk_auth_flag = 0;
            for(unsigned int i = 0; i< sdk_cap_info.caps_num; i++){
                if (sdk_cap_info.caps[i].cap_id == QXWZ_SDK_CAP_ID_NOSR && sdk_cap_info.caps[i].state == QXWZ_SDK_CAP_STATE_INSERVICE){
                    qxwz_sdk_start(QXWZ_SDK_CAP_ID_NOSR);   /* start LSSR capability */
                }
            }
        }
    }

    qxwz_sdk_stop(QXWZ_SDK_CAP_ID_NOSR);   /* stop NOSR capability */

END:
    qxwz_sdk_cleanup();
}



/*******************************************************************************
 * 名称：getSdkVersion
 * 功能：获取SDK版本
 * 参数：无
 * 返回：含有SDK版本信息的字符串
 * 说明：版本号最大长度XX字节
 *******************************************************************************/
static int luat_qxwzgetSdkVersion(lua_State* L)
{
    lua_pushfstring(L, "%s",qxwz_sdk_version());
    //lua_pushfstring(L, "%s","qxwz_sdk_version");
    return 1;
}

/*******************************************************************************
 * 名称：getBuildInfo
 * 功能：获取Build Info
 * 参数：无
 * 返回：含有Build信息的字符串
 * 说明：最大长度XX字节
 *******************************************************************************/
static int luat_qxwzgetBuildInfo(lua_State* L)
{
    lua_pushfstring(L, "%s",qxwz_sdk_get_build_info());
    //lua_pushfstring(L, "%s","qxwz_sdk_get_build_info");
    return 1;
}

void luat_qxwzsdk_init(lua_State *L) { // 函数声明在luat_base.h里
    LLOGD("qxwz sdk init begin ...");

    LLOGD("QXWZ Version %s",qxwz_sdk_version());

    LLOGD("QXWZ Build Info %s",qxwz_sdk_get_build_info());

    // 添加全局函数
    lua_pushcfunction(L, luat_qxwzgetSdkVersion); 
    lua_setglobal(L, "qxwzgetSdkVersion");            
    lua_pushcfunction(L, luat_qxwzgetBuildInfo); 
    lua_setglobal(L, "qxwzgetBuildInfo");            

    /*
    lua_pushcfunction(L, luat_cmccsdkconstructAuthRequest); 
    lua_setglobal(L, "cmccsdkconstructAuthRequest");            
    lua_pushcfunction(L, luat_cmccsdkconstructAuthRequest_fr_ep); 
    lua_setglobal(L, "cmccsdkconstructAuthRequest_fr_ep");            
    lua_pushcfunction(L, luat_cmccsdkhandleAuthResponse); 
    lua_setglobal(L, "cmccsdkhandleAuthResponse");            
    lua_pushcfunction(L, luat_cmccsdkconstructEphRequest); 
    lua_setglobal(L, "cmccsdkconstructEphRequest");            
    lua_pushcfunction(L, luat_cmccsdkconstructRtcmRequest); 
    lua_setglobal(L, "cmccsdkconstructRtcmRequest");            
    lua_pushcfunction(L, luat_cmccsdkconstructRtcmIonoRequest); 
    lua_setglobal(L, "cmccsdkconstructRtcmIonoRequest");            
    lua_pushcfunction(L, luat_cmccsdkhandleRtcmResponse); 
    lua_setglobal(L, "cmccsdkhandleRtcmResponse");            
    lua_pushcfunction(L, luat_cmccsdksetGridNetMode); 
    lua_setglobal(L, "cmccsdksetGridNetMode");            
    lua_pushcfunction(L, luat_cmccsdksetLogThreshold); 
    lua_setglobal(L, "cmccsdksetLogThreshold");            
    lua_pushcfunction(L, luat_cmccsdkgetSdkVersion); 
    lua_setglobal(L, "cmccsdkgetSdkVersion");            
    */

    LLOGD("qxwz sdk init done");
    return; // 暂不需要返回值.
}